﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Hangfire.HttpJob.CSRedis.JobAgent.Middleware
{
    /// <summary>
    /// agent job 远程作业中间件
    /// </summary>
    internal class AgentJobMiddleware
    {
        readonly RequestDelegate _next;
        readonly ILogger<AgentJobMiddleware> _logger;
        readonly IHttpClientFactory _httpClientFactory;

        /// <summary>
        /// ctor
        /// </summary>
        public AgentJobMiddleware(
            RequestDelegate next,
            ILogger<AgentJobMiddleware> logger,
            IHttpClientFactory httpClientFactory)
        {
            _next = next;
            _logger = logger;
            _httpClientFactory = httpClientFactory;
        }

        /// <summary>
        /// invoke
        /// </summary>
        public async Task InvokeAsync(HttpContext context)
        {
            context.Request.EnableBuffering();
            context.Request.Body.Seek(0, SeekOrigin.Begin);
            using var reader = new StreamReader(context.Request.Body);
            var content = await reader.ReadToEndAsync();
            if (!string.IsNullOrWhiteSpace(content))
            {
                var callback = new CallBackData();
                AgentJobContext jobContext = null;
                var watch = Stopwatch.StartNew();
                try
                {
                    jobContext = JsonConvert.DeserializeObject<AgentJobContext>(content);
                    callback.JobId = jobContext.TaskId;
                    var job = context.RequestServices.GetServices<IAgentJob>()?.FirstOrDefault(m => jobContext.JobName == m.JobName);
                    if (job == null)
                    {
                        _logger.LogInformation("未找到对应类型服务:{0}", JsonConvert.SerializeObject(jobContext));
                        callback.Result = "未找到对应的服务类型";
                    }
                    else
                        callback.Result = await job.ExectuteAsync(jobContext);
                        
                    callback.IsSuccess = true;
                }
                catch (Exception e)
                {
                    _logger.LogError("异常:{0},{1}", e.Message, e.StackTrace);
                    callback.Result = $"{e.Message}{Environment.NewLine}{e.StackTrace}";
                }
                finally { watch.Stop(); callback.Duration = watch.ElapsedMilliseconds; }

                try
                {
                    if (!string.IsNullOrWhiteSpace(callback.JobId))
                        await _httpClientFactory.CreateClient()
                            .PostAsync(jobContext.ServerUrl, new StringContent(JsonConvert.SerializeObject(callback), Encoding.UTF8, "application/json"));
                }
                catch(Exception e)
                {
                    _logger.LogError("回调服务异常:{0}|{1},{2}", JsonConvert.SerializeObject(callback), e.Message, e.StackTrace);
                }
            }
        }
    }
}
